home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c
- Path: in1.uu.net!world!mv!usenet
- From: ENGR@GSSI.MV.COM (Michael Furman)
- Subject: Re: Fastest way to computer log(base2) of x?
- Message-ID: <DLsnt4.48s@mv.mv.com>
- Mime-Version: 1.0
- Organization: GSSI
- Date: Fri, 26 Jan 1996 15:17:27 GMT
- References: <4e61iu$p6e@villa.fc.net>
- X-Newsreader: WinVN 0.93.10
- X-Nntp-Posting-Host: gssi.mv.com
-
- In article <4e61iu$p6e@villa.fc.net>, avinash@paranoia.com says...
- >
- >[And no, this is not for a homework exercise.]
- >[BTW, the non-abridged C FAW at http://www.eskimo.com/~scs/C-faq.top.html
- >does not seem to be accessible??]
- >
- >I am trying to find out what could be the fastest way to compute
- >the position of the highest bit in any given integer -- basically, the
- >logarithm to the base 2 of any number.
- >
- >Simplistically, one could do :
- >logbase2(int x)
- >{
- > if (IS_SET_BIT_31(x)) return 31;
- > if (IS_SET_BIT_30(x)) return 30;
- > etc.
- >}
- >
- >An improvement would be to check for BITS_31_16 and BITS_15_0 at first, and
- >then check for BITS_31_24, and BITS_23_16, etc .. (divide problem in half
- >at each stage).
- >
- >Any thoughts or other ideas?
-
- If you know that it is power of 2 - you can just use '1' bits counting
- algorithm for x-1:
-
- int bitcnt(unsigned long x) // calculates number of
- '1' bits in word
- {
- unsigned long w;
- w = (x & 0x55555555l) + ((x >> 1) & 0x55555555l);
- w = (w & 0x33333333l) + ((w >> 2) & 0x33333333l);
- w = w + (w >> 4);
- w = (w & 0x000F000F) + ((w >> 8) & 0x000F000F);
- return (int)((w + (w >> 16)) & 0xFF);
- }
-
- int log2(unsigned long x)
- {
- assert(x != 0);
- return bitcnt(x - 1);
- }
-
- If not - you can make all lower bits "1" by the following code:
-
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
-
- But it is "theoretical" solution (using o(log(n)) time where n is number of
- bits in word. In reality I would rather reccomend two methods:
-
- 1. Using special CPU command. Intel 386+ hav one.
- 2. Using directly indexed table (al least for byte - 256 byte size). And
- check four bytes one by one:
-
- result = tab[(x >> 24) & 0xFF];
- if(result != 0)
- return result - 1 + 24;
-
- result = tab[(x >> 16) & 0xFF];
- if(result != 0)
- return result - 1 + 16;
- ............
-
- Note: all code are just samples and are not tested. But I used these
- algorithms a number of times - they works.
- >
- >Thanks!
- >
- >--
- >----
- >Avinash Chopde
- >e-mail: avinash@acm.org
- >home page: http://www.paranoia.com/~avinash/
-
- --
- <<<<<<<< This is a copy of post to the newsgroup >>>>>>>>
- ---------------------------------------------------------------
- Michael Furman, (603)893-1109
- Geophysical Survey Systems, Inc. fax:(603)889-3984
- 13 Klein Drive - P.O. Box 97 engr@gssi.mv.com
- North Salem, NH 03073-0097 71543.1334@compuserve.com
- ---------------------------------------------------------------
-
-